package com.handydata.antifraud.channel.outbound;

import java.util.Map;
import java.util.UUID;

import com.handydata.common.util.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.handydata.antifraud.common.constant.AlarmInfoCode;
import com.handydata.antifraud.crypt.MessageCryptoHandler;
import com.handydata.antifraud.enums.RiskReturnEnum;
import com.handydata.antifraud.service.AlarmInfoService;
import com.handydata.antifraud.util.HttpUtil;
import com.handydata.antifraud.util.encrypt.Base64Utils;
import com.handydata.antifraud.util.encrypt.DesUtils;
import com.handydata.antifraud.util.encrypt.Md5Utils;
import com.handydata.antifraud.util.encrypt.RSACoderUtils;
import com.handydata.antifraud.vo.riskres.RiskOutputVO;
import com.handydata.common.exception.SysException;
@Component
public class RiskResultSendBack {

    private static final Logger logger = LoggerFactory.getLogger(RiskResultSendBack.class);

    @Value("${risk.shbank.private-key}")
    private String privateKey;

    @Value("${risk.shbank.public-key}")
    private String publicKey;

    @Value("${risk.shbank.sendback.url1}")
    private String sendUrl1;

    @Value("${risk.shbank.sendback.url2}")
    private String sendUrl2;


    @Autowired
    private MessageCryptoHandler messageCryptoHandler;

    @Autowired
    private AlarmInfoService alarmInfoService;

    @Autowired
    RedisUtil redisUtil;

    @Value("${risk.shbank.sendback.timeOut:30000}")
    private int timeOut;
    private long expireTime;
    public boolean doAction(RiskOutputVO riskOutputVO) {
        try {
        	logger.info("推送数据给上行订单号{}", riskOutputVO.getOrderId());
            String redisKey="order_"+riskOutputVO.getOrderId();
            Integer sendOver=(Integer)redisUtil.get(redisKey);
//            redisUtil.set(redisKey,4);
//            return true;
            if(sendOver!=4){
                String encryptMsg =encrypt1(riskOutputVO.getJSONString());
                logger.info("推送数据给上行-加密后参数:超时时间 {} {}", timeOut,encryptMsg);
                logger.info("推送给上行url地址： {}",sendUrl1);
                String res = HttpUtil.sendDataByPost(sendUrl1, encryptMsg,timeOut);//通道1
                if(HttpUtil.CONNECT_TIMED_OUT.equals(res)){
                	logger.error("通道 {} 推送风控结果给上行失败",sendUrl1);
                    logger.info("换通道推送给上行 {}",sendUrl2);
                    res = HttpUtil.sendDataByPost(sendUrl2, encryptMsg,timeOut);//通道2
                    if(HttpUtil.CONNECT_TIMED_OUT.equals(res)){
                    	logger.error("换通道 {} 推送风控结果给上行失败",sendUrl2);
                    	expireTime = redisUtil.getExpire(redisKey);
						redisUtil.set(redisKey, 5, expireTime);
                    }
                }
                if(StringUtils.isEmpty(res)){
                    alarmInfoService.sendWatchAbNormal(AlarmInfoCode.ALERT_ITEM_ORDER.getCode(),
                            riskOutputVO.getOrderId(),null,AlarmInfoCode.ALARM_TYPE_ERR.getCode(),"发送上行计算结果出错：网络异常",null);
                    return  false;
                }
                logger.info("发送订单号为{}计算结果给上行,上行返回密文{}",riskOutputVO.getOrderId(),res);

                String[] arry = res.split("\\|");
                if(arry.length==3){
                    Map<String, Object> decryptRes = JSONObject.parseObject(decrypt1(arry));
                    logger.info("发送订单号为{}计算结果给上行,上行返回明文{}",riskOutputVO.getOrderId(),decryptRes);

                    if("00000".equals(decryptRes.get("resultCode"))) {
                    	expireTime = redisUtil.getExpire(redisKey);
						redisUtil.set(redisKey, 4, expireTime);
                        return true;
                    } else {
                    	expireTime = redisUtil.getExpire(redisKey);
						redisUtil.set(redisKey, 5, expireTime);
                    }
                    alarmInfoService.sendWatchAbNormal(AlarmInfoCode.ALERT_ITEM_ORDER.getCode(),
                            riskOutputVO.getOrderId(),null,AlarmInfoCode.ALARM_TYPE_ERR.getCode(),"发送上行计算结果出错: "+JSON.toJSONString(decryptRes),null);

                    return false;
                }else{

                    alarmInfoService.sendWatchAbNormal(AlarmInfoCode.ALERT_ITEM_ORDER.getCode(),
                            riskOutputVO.getOrderId(),null,AlarmInfoCode.ALARM_TYPE_ERR.getCode(),"发送上行计算结果出错: "+res,null);
                    return false;

                }
            }else{
                logger.info("该订单已发送给上行，不再重复发送{}",riskOutputVO.getOrderId());
                return  true;
            }
        }catch (Exception ex){
            alarmInfoService.sendWatchAbNormal(AlarmInfoCode.ALERT_ITEM_ORDER.getCode(),
                    riskOutputVO.getOrderId(),null,AlarmInfoCode.ALARM_TYPE_ERR.getCode(),"发送上行异常",ex);
            logger.error("发送给上行结果失败",ex);
            return  false;
        }

    }
    /**
     * 发送给上行的数据---私钥加密
     * @param param
     * @return
     */
    private String encrypt1(String param) {
        String result = "";
        try {
            // 加密第一段数据
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String rsaUuid = RSACoderUtils.encryptByPrivateKey(uuid, privateKey);
            String base64RsaUuid = Base64Utils.encode(rsaUuid.getBytes());
            // 加密第二段数据
            byte[] desTxt = DesUtils.encrypt(param.getBytes("UTF-8"), uuid.getBytes("UTF-8"));
            String baseDesTxt = Base64Utils.encode(desTxt);
            // 加密第三段数据
            String md5Uuid = Md5Utils.md5ToHexStr(uuid);
            String base64Md5Uuid = Base64Utils.encode(md5Uuid.getBytes());
            result = base64RsaUuid + "|" + baseDesTxt + "|" + base64Md5Uuid;
        } catch (Exception e) {
            throw new SysException(RiskReturnEnum.DECRYPT_DATA_ERROR.getCode(), RiskReturnEnum.DECRYPT_DATA_ERROR.getText());
        }
        return result;
    }
    /**
     * 上行返回响应结果---公钥解密
     * @param arry
     * @return
     */
    private String decrypt1(String[] arry) {
        String result = "";
        try {
//			String[] arry = str.split("\\|");
            if (arry.length != 3) {
                //			return "0|" + DsCons.FORMAT_ERROR + "|" + Base64Utils.encode("数据格式错误".getBytes());
                throw new SysException(RiskReturnEnum.DATA_FORMAT_ERROR.getCode(), RiskReturnEnum.DATA_FORMAT_ERROR.getText());
            }
            // 解密第一段
            byte[] rsaUuidByte = Base64Utils.decode(arry[0]);
            String rsaUuidDecrypt = new String(rsaUuidByte, "UTF-8");
            String desKey = RSACoderUtils.decryptByPublicKey(rsaUuidDecrypt, publicKey);
            // 解密第二段
            byte[] baseDesTxtByte = Base64Utils.decode(arry[1]);
            byte[] newTxtByte = DesUtils.decrypt(baseDesTxtByte, desKey.getBytes());
//			String content = new String(newTxtByte, "UTF-8");
            result = new String(newTxtByte, "UTF-8");
            // 解密第三段验证签名
            String newMd5Uuid = Md5Utils.md5ToHexStr(desKey);
            String newBase64Md5Uuid = Base64Utils.encode(newMd5Uuid.getBytes());
            if (!arry[2].equals(newBase64Md5Uuid)) {
                throw new SysException(RiskReturnEnum.CHECK_SIGN_ERROR.getCode(), RiskReturnEnum.CHECK_SIGN_ERROR.getText());
            }
        } catch (Exception e) {
            throw new SysException(RiskReturnEnum.DECRYPT_DATA_ERROR.getCode(), RiskReturnEnum.DECRYPT_DATA_ERROR.getText());
        }
        return result;
    }
}
